
<template>
  <el-tree ref="selectTree" :data="handleTreeData" :props="options"
           :node-key="dataConfig.idField"
           :show-checkbox="showCheckBox"  :check-strictly="true"
           @check="handleCheckChange" @nodeClick="treeNodeClick">
  </el-tree>
</template>
<script setup lang="ts">

import {computed, nextTick, ref, toRaw} from "vue";
import {assembleTreeData} from "@/utils/useTreeData.ts";
import {CheckedModel, ExpandedModel, type TreeView} from "@/components/plugs/tree/TreeView.ts";

const props = withDefaults(defineProps<TreeView>(),{
  dataConfig: {
    simple: true,
    pFiled:'',
    idField: '',
    rootId: ''
  } as any,
  showCheckBox: true,
  options: {} as any,
  checkedModel: CheckedModel.MULTIPLE_NO_CASCADE,
  expandedModel: ExpandedModel.MULTIPLE,
  checkedChange:(node:object,checked:boolean,allCheckedData:object) => {},
  nodeClick: (data:object,_node:object) => {}
});
const selectTree:any = ref(null);
const  {treeData,options,dataConfig,checkedModel,checkedChange,nodeClick,expandedModel} = props;

const handleTreeData = computed(() => {
  if(dataConfig != undefined && dataConfig.simple){
    return assembleTreeData(treeData,dataConfig.pFiled,dataConfig.idField,dataConfig.rootId);
  }
  return treeData;
});

const treeNodeClick = (data:object,_node:object) =>{
  if(expandedModel == ExpandedModel.SINGLE){
    collapseAll();
    expandedParent(_node);
  }
  nodeClick(data,_node);
}

const collapseAll = () =>{
  const allNodes = selectTree.value.store.nodesMap; // 获取所有节点的引用
  Object.keys(allNodes).forEach(key => {
    allNodes[key].collapse(); // 折叠每个节点
  });
}

const expandedParent= (_node:object) => {
  _node.expanded = true;
  if(_node.parent){
    expandedParent(_node.parent);
  }
}

const handleCheckChange = (node:object,checkObj:object) => {
  const checkedKeys = checkObj.checkedKeys;
  let checked = false;
  for(const item of checkedKeys){
    if(item == node.id){
      checked = true;
      break;
    }
  }
  if(checkedModel == CheckedModel.SINGLE){
    singleChecked(node,checkObj);
  }else if(checkedModel == CheckedModel.CASCADE){
    cascadeParentChecked(node,checked,checkedKeys);
    cascadeChildChecked(node,checked);
  }
  checkedChange(node,checked,selectTree.value.getCheckedNodes());
}

const cascadeParentChecked = (node:object,checked:boolean,checkedKeys:any) =>{
  if(node.pNode == undefined){
    return;
  }
  if(checked){
    let flag = false;
    for(const item of checkedKeys){
      if(item == node.pNode[dataConfig.idField]){
        flag = true;
      }
    }
    if(flag){
      return;
    }
    checkedKeys.push( node.pNode[dataConfig.idField])
  }else {
    const children = node.pNode.children;
    let childFlag = false;
    for(const  item of children){
      for(const checkedItem of checkedKeys){
        if(item[dataConfig.idField] == checkedItem){
          childFlag = true;
        }
      }
    }
    if(!childFlag){
      checkedKeys = checkedKeys.filter((item:string) => item != node.pNode[dataConfig.idField]);
    }
  }

  selectTree.value.setCheckedKeys(checkedKeys);
  cascadeParentChecked(node.pNode,checked,checkedKeys);
}

const cascadeChildChecked = (node:object,checked:boolean) => {

  if(node.children == undefined){
    return;
  }
  node.children.forEach( (child:any) => {
    selectTree.value.setChecked(child.id, checked, true);
    if(child.children != undefined){
      cascadeChildChecked(child,checked);
    }
  });
}

const checkCurrentLevelNodeCheckedStatus = (node:object) => {
  const checkedNode = selectTree.value.getCheckedNodes();

}

const findParentNodeKey = (node:object) =>{
  const vNode:any = toRaw(node);
  for(let item of treeData){
    if(item[dataConfig.idField] == vNode[dataConfig.pFiled]){
      return item;
    }
  }
}

const singleChecked = (node:{[key : string] : any},checkObj:object) => {
  if (checkObj.checkedKeys.length > 1) {
    selectTree.value.setCheckedKeys([node[dataConfig.idField]]);
  }
}

//暴露方法
const setCheckedKeys = (idkeys:[]) => {
  nextTick(() =>{
    selectTree.value.setCheckedKeys(idkeys);
  });
}

const getCheckedNodes = () =>{
  return selectTree.value.getCheckedNodes();
}

const getCheckedKeys = () => {
  return selectTree.value.getCheckedKeys();
}

defineExpose({setCheckedKeys,getCheckedNodes,getCheckedKeys});

</script>

<style scoped>

</style>